//--------------------------------------------------------------
//
// Qizhi Zhang 
// ezhung@gmail.com
// http://www.moorwind.com
//
//--------------------------------------------------------------
package reader.dao
{
	import flash.data.SQLConnection;
	import flash.data.SQLResult;
	import flash.data.SQLStatement;
	import flash.utils.Dictionary;
	
	public class BaseDAO implements IBaseDAO
	{
		//////////////////////////////////////////////////////////////////////////////
		//protected properties
		protected const MAX_PREFETCH:uint = 50;
		protected const MAX_DATA:uint = 100;
		
		protected var connection:SQLConnection;
		protected var queries:Dictionary;
		
		protected function get delayCommitInterval():uint
		{
			return uint(Math.random()* 500) + 200;
		}
		
		//////////////////////////////////////////////////////////////////////////////
		//constructor
		public function BaseDAO(connection:SQLConnection)
		{
			this.connection = connection;
			this.queries = new Dictionary();
		}
		
		//////////////////////////////////////////////////////////////////////////////
		//methods
		
		public function execute(query:String, parameters:Object, prefetch:int = -1):SQLResult
        {
            var sqlStatement:SQLStatement = SQLStatement(queries[query]);
            if (sqlStatement == null)
            {               
                sqlStatement = new SQLStatement();
                queries[query] = sqlStatement;               
                sqlStatement.sqlConnection = connection;
                sqlStatement.text = query;
            }
            sqlStatement.clearParameters();            
            if (parameters != null)
            {
                for (var name:String in parameters)
                {
                    // To make parameter object creation easier the standard
                    // ":" prefix is added here when setting the value. 
                    sqlStatement.parameters[":" + name] = parameters[name];
                }
            }
            
            try
			{
				sqlStatement.execute(prefetch);
			}
			catch(e:Error)
			{
				trace(e);
			}
			
			//Handle the results of the execution.
			var result:SQLResult = sqlStatement.getResult();
			if (!result || !result.complete)
            {
                sqlStatement.cancel();
            }
            return result;
        }
        
        public function executeTransaction(query:String, parameters:Object, prefetch:int = -1):SQLResult
        {
            var sqlStatement:SQLStatement = new SQLStatement();
            sqlStatement.sqlConnection = connection;
            sqlStatement.text = query;
            if (parameters != null)
            {
                for (var name:String in parameters)
                {
                    // To make parameter object creation easier the standard
                    // ":" prefix is added here when setting the value. 
                    sqlStatement.parameters[":" + name] = parameters[name];
                }
            }
            
            try
			{
				sqlStatement.execute(prefetch);
			}
			catch(e:Error)
			{
				trace(e);
			}
			
			//Handle the results of the execution.
			var result:SQLResult = sqlStatement.getResult();
            return result;
        }
        
        public function update(query:String, data:Object):Boolean
        {
        	var sqlResult:SQLResult = execute(query, data);
            return sqlResult.rowsAffected != 0;
        }
        
        public function drop(query:String, data:Object):Boolean
        {
        	var sqlResult:SQLResult = execute(query, data);
            return sqlResult.rowsAffected != 0;
        }
        
        public function count(query:String, data:Object):uint
        {
        	var result:SQLResult = execute(query, data);
        	if(!result || !result.data)
			{
				return 0;
			}
			
			var _data:Object = result.data[0];
			var _count:uint = 0;
			for each(var obj:uint in _data)
			{
				_count = obj;
			}
			return _count;
        }
        
        protected function callLaterCommit():void
		{
			try
			{
				if(!this.connection.inTransaction)
				{
					this.connection.commit();
				}
			}
			catch(e:Error)
			{
				trace(e);
			}
		}
	}
}